﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Linq;
using System.IO;

namespace ConsoleApp
{
    public class ReflectionDemo
    {
        private static string saveFilePath = @"E://";
        private static string readFilePath = @"E://";

        public void Show()
        {
            var obj = Assembly.LoadFrom(@"C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Runtime.dll");
            var type = typeof(String);

            Console.WriteLine("-----------GetMethods-------------");
            foreach (var item in type.GetMethods())
            {
                Console.WriteLine(item.Name);
            }
            Console.WriteLine("-----------GetProperties-------------");
            foreach (var item in type.GetProperties())
            {
                Console.WriteLine(item.Name);
            }
            Console.WriteLine("-----------GetFields-------------");
            foreach (var item in type.GetFields())
            {
                Console.WriteLine(item.Name);
            }
        }

        public void GetDBModol()
        {
            WriteFile(GetDataDllTypes()[0]);
        }
        static Type[] GetDataDllTypes()
        {
            //Assembly assembly = Assembly.LoadFrom(@"C:\Work\WorkArea2\IMCOA\IMCOA.BusinessService\bin\Debug\IMCOA.Data.dll");
            Assembly assembly = Assembly.LoadFrom(@"C:\Work\WorkArea2\IMCOA\IMCOA.BusinessService\bin\Debug\IMCOA.Sale.Sku.Data.dll"); 
             var types = assembly.GetTypes();
            return types.Where(x => x.Name.Contains("ORDERPARENT")).ToArray();
        }

        static void WriteFile(Type type)
        {
            List<string> descLines = ReadPropertyDescription(type.Name);

            StringBuilder sb = new StringBuilder();
            StringBuilder sbMap = new StringBuilder();
            var properties = type.GetProperties().Where(x => x.CanRead && x.CanWrite);

            foreach (var propertyInfo in properties)
            {

                sb.Append($"/// <summary>{Environment.NewLine}");
                sb.Append($"/// {GetDescription(descLines, propertyInfo.Name)}{ Environment.NewLine}");
                sb.Append($"/// </summary>{ Environment.NewLine}");
                sb.Append($"public { GetPropertyTypeString(propertyInfo.PropertyType.FullName)} {GetPropertyName(propertyInfo.Name)} {{get;set;}}{Environment.NewLine}");
                sb.Append(Environment.NewLine);

                sbMap.Append($"CreateMap<{type.Name}, {GetPropertyName(type.Name)}Model>().ForMember(dest => dest.{GetPropertyName(propertyInfo.Name)}, opt => opt.MapFrom(src => src.{propertyInfo.Name})).ReverseMap();{Environment.NewLine}");

            }

            using (StreamWriter sw = new StreamWriter(saveFilePath + $"\\{type.Name}.txt", false, Encoding.UTF8))
            {
                sw.WriteLine(sb.ToString());
            }
            using (StreamWriter sw = new StreamWriter(saveFilePath + $"\\{type.Name}Profile.txt", false, Encoding.UTF8))
            {
                sw.WriteLine(sbMap.ToString());
            }
        }
        static string GetDescription(List<string> lines, string popeName)
        {
            var tempName = $"{popeName}\t";
            var desc = lines.FirstOrDefault(x => x.StartsWith(tempName));
            if (string.IsNullOrWhiteSpace(desc))
                return popeName;
            else
            {
                return desc.Replace(tempName, "").Trim();
            }
        }
        static List<string> ReadPropertyDescription(string typeName)
        {
            List<string> lines = new List<string>();
            string filepath = Path.Combine(readFilePath, typeName);
            if (!File.Exists(filepath)) return lines;
            using (StreamReader streamReader = new StreamReader(filepath, Encoding.UTF8))
            {
                while (!streamReader.EndOfStream)
                {
                    lines.Add(streamReader.ReadLine());
                }
            }
            return lines;
        }

        static string GetPropertyName(string propertyName)
        {
            var splitItems = propertyName.Split('_');
            List<string> itemList = new List<string>();
            foreach (var str in splitItems)
            {
                var temp = str.ToLower();
                temp = str.Substring(0, 1) + temp.Remove(0, 1);
                itemList.Add(temp);
            }
            return string.Join("", itemList);
        }
        static string GetPropertyTypeString(string propertyTypeStr)
        {

            switch (propertyTypeStr)
            {
                case "System.Nullable`1[[System.Int16, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]":
                    return "short?";
                case "System.Nullable`1[[System.DateTime, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]":
                    return "DateTime?";
                case "System.Nullable`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]":
                    return "int?";
                case "System.Nullable`1[[System.Decimal, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]":
                    return "decimal?";
                case "System.DateTime":
                    return "DateTime";
                case "System.String":
                    return "string";
                case "System.Int32":
                    return "int";
                case "System.Int16":
                    return "short";
                case "System.Decimal":
                    return "decimal";
                default:
                    return propertyTypeStr;
            }
        }


    }
}
